#include "Rational.h"
	
Rational::Rational(): up(0), down(1)
{
}

Rational::Rational(int up, int down): up(up), down(down)
{
}

Rational& Rational::operator += (const Rational & a)
{
	return *this = (*this) + a;
}

Rational& Rational::operator -= (const Rational & a)
{
	return *this = *this - a;
}

Rational& Rational::operator *= (const Rational & a)
{
	return *this = *this * a;
}

Rational& Rational::operator /= (const Rational & a)
{
	return *this = *this / a;
}

Rational Rational::Inverse() const
{
	return Rational(down, up);
}
	
Rational Rational::operator - () 
{
	return Rational(-up, down);
}

Rational::operator double()
{
	return double(up) / down;
}

Rational& Rational::operator ++ ()
{
	return *this += 1;
}

Rational Rational::operator ++ (int)
{
	Rational ret = *this;
	*this += 1;
	return ret;
}

Rational& Rational::operator -- ()
{
	return *this -= 1;
}

Rational Rational::operator -- (int)
{
	Rational ret = *this;
	*this -= 1;
	return ret;
}

int Rational::GCD(int a, int b)
{
	return b == 0 ? a : GCD(b, a % b);
}

void Rational::ToCommonDenominator(Rational & a, Rational & b)
{
	int nextDown = a.down * b.down / Rational::GCD(a.down, b.down);
	a.up *= nextDown / a.down;
	b.up *= nextDown / b.down;
	a.down = b.down = nextDown;
}

void Rational::MakeTrue()
{
	int gcd = Rational::GCD(down, up);
	up /= gcd;
	down /= gcd;
}

bool operator == (const Rational & a, const Rational & b)
{
	Rational aTemp(a);
	Rational bTemp(b);
	Rational::ToCommonDenominator(aTemp, bTemp);
	return aTemp.up == bTemp.up;
}

bool operator != (const Rational & a, const Rational & b)
{
	return !(a == b);
}

bool operator <= (const Rational & a, const Rational & b)
{
	return a == b || a < b;
}

bool operator < (const Rational & a, const Rational & b)
{
	Rational aTemp(a);
	Rational bTemp(b);
	Rational::ToCommonDenominator(aTemp, bTemp);
	return aTemp.up < bTemp.up;
}

bool operator >= (const Rational & a, const Rational & b)
{
	return a == b || a > b;
}


bool operator > (const Rational & a, const Rational & b)
{
	return (a != b) && !(a < b); 
}


Rational operator + (const Rational & a, const Rational & b)
{
	Rational aTemp(a);
	Rational bTemp(b);
	Rational::ToCommonDenominator(aTemp, bTemp);
	Rational ret(aTemp.up + bTemp.up, aTemp.down);
	ret.MakeTrue();
	return ret;
}

Rational operator - (const Rational & a, const Rational & b)
{
	return a + (-Rational(b));
}

Rational operator * (const Rational & a, const Rational & b)
{
	Rational ret(a.up * b.up, a.down * b.down);
	ret.MakeTrue();
	return ret;
}

Rational operator / (const Rational & a, const Rational & b)
{
	return a * b.Inverse();
}

ostream& operator << (ostream & out, const Rational & a)
{
	if((a.up > 0 && a.down < 0) || (a.up < 0 && a.down > 0))
	{
		out << '-';
	}
	return out << abs(a.up)  << '/' << abs(a.down);
}

